/*
 * Copyright [vega-ai-sdk] [rightbrain.art]
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 * According to vega feature, we modify some class，comment, field name, etc.
 */

package com.rightbrain.vegaai.tool.sdk.config;

import lombok.extern.slf4j.Slf4j;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.RegistryBuilder;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.conn.socket.PlainConnectionSocketFactory;
import org.apache.http.conn.ssl.SSLConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import org.apache.http.ssl.SSLContextBuilder;
import org.apache.http.ssl.TrustStrategy;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;

import javax.net.ssl.SSLContext;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.X509Certificate;

/**
 * HttpClientConfig.
 */
@Slf4j
@Configuration
public class HttpClientConfig {

    @Value("${vega.http.maxTotal:500}")
    private Integer maxTotal;//最大连接数

    @Value("${vega.http.defaultMaxPerRoute:100}")
    private Integer defaultMaxPerRoute;//支持并发数

    @Value("${vega.http.connectTimeout:3000}")
    private Integer connectTimeout;//连接的超时时间

    @Value("${vega.http.connectionRequestTimeout:500}")
    private Integer connectionRequestTimeout;//从连接池获取连接的超时时间

    @Value("${vega.http.socketTimeout:10000}")
    private Integer socketTimeout;//数据传输超时时间

    private static SSLContext sslContext = null;

    static {
        try {
            sslContext = new SSLContextBuilder().loadTrustMaterial(null, new TrustStrategy() {
                //信任所有
                @Override
                public boolean isTrusted(X509Certificate[] xcs, String string) {
                    return true;
                }
            }).build();
        } catch (KeyStoreException ex) {
            log.error(ex.getMessage(), ex);
            ex.printStackTrace();
        } catch (NoSuchAlgorithmException ex) {
            log.error(ex.getMessage(), ex);
            ex.printStackTrace();
        } catch (KeyManagementException ex) {
            log.error(ex.getMessage(), ex);
            ex.printStackTrace();
        }
    }

    /**
     * 实例化一个连接池管理器,并且设置最大连接数，支持并发数
     *
     * @return
     */

    @Bean(name = "vegaHttpClientConnectionManager")
    public PoolingHttpClientConnectionManager getHttpClientConnectionManager() {
        Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder.<ConnectionSocketFactory>create()
                .register("http", new PlainConnectionSocketFactory())
                .register("https", new SSLConnectionSocketFactory(sslContext, SSLConnectionSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER))
                .build();
        PoolingHttpClientConnectionManager httpClientConnectionManager = new PoolingHttpClientConnectionManager(socketFactoryRegistry);
        httpClientConnectionManager.setMaxTotal(maxTotal);
        httpClientConnectionManager.setDefaultMaxPerRoute(defaultMaxPerRoute);
        return httpClientConnectionManager;
    }

    /**
     * 实例化连接池，设置连接池管理器。
     * <p>
     * 这里需要以参数形式注入上面实例化的连接池管理器
     *
     * @param httpClientConnectionManager
     * @return
     */
    @Bean(name = "vegaHttpClientBuilder")
    public HttpClientBuilder getHttpClientBuilder(@Qualifier("vegaHttpClientConnectionManager") PoolingHttpClientConnectionManager httpClientConnectionManager) {
        HttpClientBuilder builder = HttpClientBuilder.create();
        builder.setConnectionManager(httpClientConnectionManager);
        return builder;
    }

    /**
     * 注入连接池，用于获取httpClient
     *
     * @param httpClientBuilder
     * @return
     */
    @Bean(name = "vegaHttpClient")
    public CloseableHttpClient getCloseableHttpClient(@Qualifier("vegaHttpClientBuilder") HttpClientBuilder httpClientBuilder) {
        CloseableHttpClient httpClient = httpClientBuilder.build();
        return httpClient;
    }

    /**
     * Builder是RequestConfig的一个内部类
     * <p>
     * 通过RequestConfig的custom方法来获取到一个Builder对象
     * <p>
     * 设置builder的连接信息
     * <p>
     * 这里还可以设置proxy，cookieSpec等属性。有需要的话可以在此设置
     *
     * @return
     */
    @Bean(name = "vegaBuilder")
    public RequestConfig.Builder getBuilder() {
        RequestConfig.Builder builder = RequestConfig.custom();
        return builder.setConnectTimeout(connectTimeout).
                setConnectionRequestTimeout(connectionRequestTimeout).
                setSocketTimeout(socketTimeout);
    }

    /**
     * 使用builder创建一个RequestConfig对象
     *
     * @param builder
     * @return
     */
    @Bean(name = "vegaRequestConfig")
    public RequestConfig getRequestConfig(@Qualifier("vegaBuilder") RequestConfig.Builder builder) {
        RequestConfig requestConfig = builder.build();
        return requestConfig;
    }

}
